/*
 ***************************************************************************************
 * EP for web developers.Supported By Junxworks
 * @Title:  FanRecommendServiceImpl.java   
 * @Package io.github.junxworks.qt.modules.stock.service.impl   
 * @Description: (用一句话描述该文件做什么)   
 * @author: Administrator
 * @date:   2021年10月9日 下午12:38:13   
 * @version V1.0 
 * @Copyright: 2021 Junxworks. All rights reserved. 
 * 注意：
 *  ---------------------------------------------------------------------------------- 
 * 文件修改记录
 *     文件版本：         修改人：             修改原因：
 ***************************************************************************************
 */
package io.github.junxworks.qt.modules.stock.service.impl;

import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import com.googlecode.concurrentlinkedhashmap.Weighers;

import io.github.junxworks.junx.core.util.DateUtils;
import io.github.junxworks.junx.core.util.NumberUtils;
import io.github.junxworks.junx.core.util.StringUtils;
import io.github.junxworks.qt.commons.DateHandleService;
import io.github.junxworks.qt.constants.StockRecommendStatus;
import io.github.junxworks.qt.modules.data.vo.DStockProfileVo;
import io.github.junxworks.qt.modules.stock.dto.StockChooseDto;
import io.github.junxworks.qt.modules.stock.entity.DStockRecommend;
import io.github.junxworks.qt.modules.stock.mapper.RecommendMapper;
import io.github.junxworks.qt.modules.stock.service.FanRecommendService;
import io.github.junxworks.qt.modules.tushare.entity.DStockTradeDailyBasic;
import io.github.junxworks.qt.modules.tushare.service.BaseInfoService;
import io.github.junxworks.qt.modules.tushare.service.TradeInfoService;

/**
 * 财报期间的推荐
 *
 * @ClassName:  FanRecommendServiceImpl
 * @author: Michael
 * @date:   2021年10月9日 下午12:38:14
 * @since:  v1.0
 */
@Service("FanRecommendService")
public class FanRecommendServiceImpl extends DateHandleService implements FanRecommendService {

	/** recommend mapper. */
	@Autowired
	private RecommendMapper recommendMapper;

	/** trade info service. */
	@Autowired
	private TradeInfoService tradeInfoService;

	/** base info service. */
	@Autowired
	private BaseInfoService baseInfoService;

	/** cache. */
	private ConcurrentLinkedHashMap<String, Map<String, DStockTradeDailyBasic>> cache = new ConcurrentLinkedHashMap.Builder<String, Map<String, DStockTradeDailyBasic>>().maximumWeightedCapacity(2).weigher(Weighers.singleton()).build();

	/** month. */
	private Set<Integer> month = Sets.newHashSet(0, 1, 2, 3, 6, 7, 9, 10);

	/**
	 * Recommend.
	 *
	 * @param date the date
	 */
	@Override
	public void recommend(String date) {

		handleDataByDate(date, d -> {
			if (tradeInfoService.isWeekend(d)) {
				return;
			}
			Date dd = DateUtils.parse(d, "yyyyMMdd");
			if (!month.contains(dd.getMonth())) {
				return;
			}
			String ld = tradeInfoService.queryTradeCalByOffset(d, -1);
			if (StringUtils.isNull(ld)) {
				return;
			}
			Map<String, DStockTradeDailyBasic> ltdbm = cache.get(ld);
			if (ltdbm == null) {
				List<DStockTradeDailyBasic> ltdbs = tradeInfoService.queryTradeDailyBasicByDate(ld);
				ltdbm = ltdbs.stream().collect(Collectors.toMap(t -> t.getTsCode(), t -> t));
				cache.put(ld, ltdbm);
			}
			List<DStockProfileVo> ps = baseInfoService.getAllAvailabeProfiles();
			List<StockChooseDto> res = Lists.newArrayList();
			List<DStockTradeDailyBasic> tdbs = tradeInfoService.queryTradeDailyBasicByDate(d);
			Map<String, DStockTradeDailyBasic> tdbm = tdbs.stream().collect(Collectors.toMap(t -> t.getTsCode(), t -> t));
			cache.put(d, tdbm);
			for (DStockProfileVo p : ps) {
				if (!"主板".equals(p.getMarket())) {
					continue;
				}
				String tsCode = p.getTsCode();
				DStockTradeDailyBasic tdb = tdbm.get(tsCode);
				if (tdb != null && tdb.getPeTtm() > 0) {
					DStockTradeDailyBasic ltdb = ltdbm.get(tsCode);
					if (ltdb != null) {
						//						if (tdb.getPeTtm() * 1.5 < ltdb.getPeTtm() && tdb.getPe() > ltdb.getPeTtm() && tdb.getTurnoverRateF() > ltdb.getTurnoverRateF()) {
						if (tdb.getPeTtm() * 1.5 < ltdb.getPeTtm() && ltdb.getPeTtm() < 200) {
							StockChooseDto choose = new StockChooseDto();
							choose.setStock(p);
							choose.setTdb(tdb);
							choose.setLtdb(ltdb);
							choose.setPeTtmChange(NumberUtils.devide(ltdb.getPeTtm(), tdb.getPeTtm(), 2).floatValue());
							choose.setScore(choose.getPeTtmChange() * 10);
							res.add(choose);
						}
					}
				}
			}
			recommendStock(res);
		});
	}

	/**
	 * Recommend stock.
	 *
	 * @param res the res
	 */
	private void recommendStock(List<StockChooseDto> res) {
		if (res.isEmpty()) {
			return;
		}
		res.sort(new Comparator<StockChooseDto>() {

			@Override
			public int compare(StockChooseDto o1, StockChooseDto o2) {
				return o2.getScore().compareTo(o1.getScore());
			}

		});
		res.stream().filter(f -> {
			int count = recommendMapper.queryRecommendByTsCode(f.getTdb().getTsCode());
			return count == 0;
		}).forEach(s -> {
			DStockTradeDailyBasic tdb = s.getTdb();
			DStockTradeDailyBasic ltdb = s.getLtdb();
			DStockRecommend dr = new DStockRecommend();
			dr.setModel("sql");
			dr.setBDate(tdb.getTradeDate());
			dr.setBPe(tdb.getPe());
			dr.setYPe(ltdb.getPe());
			dr.setBPeTtm(tdb.getPeTtm());
			dr.setYPeTtm(ltdb.getPeTtm());
			dr.setBTrf(tdb.getTurnoverRateF());
			dr.setYTrf(ltdb.getTurnoverRateF());
			dr.setBPrice(tdb.getClose());
			dr.setBTotalMv(tdb.getTotalMv());
			dr.setStatus(StockRecommendStatus.RECOMMEND.getValue());
			dr.setTsCode(s.getTdb().getTsCode());
			dr.setScore(s.getScore());
			recommendMapper.insertWithoutNull(dr);
		});
	}

	/**
	 * Recommend range.
	 *
	 * @param range the range
	 */
	public void recommendRange(String range) {
		cache.clear();
		handleDataDayByDay(range, 0, this::recommend);
		cache.clear();
	}
}
